from fastapi import Request, Response, Query, APIRouter, Depends
from sqlalchemy.orm import Session
import httpx
from common.log import logger
from config import base_config
import hashlib
from common.WXBizJsonMsgCrypt import WXBizJsonMsgCrypt 
import json
from pydantic_models import WXWorkIn
from common.message_dedup import get_message_deduplicator
from kqk_workflow import get_kqk_workflow
from common.chat_handler import ChatHandler
from common.enum_types import ActionType
from models import get_db
import traceback

kqk_router = APIRouter(prefix="/kqk", tags=["KQK Services"])

def verify_signature(signature: str, timestamp: str, nonce: str) -> bool:
    """验证签名是否合法"""
    tmp_list = sorted([base_config.ROBOT_TOKEN, timestamp, nonce])  # 字典序排序
    tmp_str = "".join(tmp_list)
    tmp_sha1 = hashlib.sha1(tmp_str.encode("utf-8")).hexdigest()
    return tmp_sha1 == signature

@kqk_router.get("/healthcheck", tags=["APP Health check"], summary="Kumquat King health check",
         description="Kumquat King health check",
         response_description="APP it's running.")
async def hello(db: Session = Depends(get_db)):
    """健康检查接口，验证数据库连接"""
    try:
        # 测试数据库连接
        db.execute("SELECT 1")
        return f"{base_config.APP_NAME} is running with database connected."
    except Exception as e:
        logger.error(f"[健康检查] ❌ 数据库连接失败: {e}")
        return f"{base_config.APP_NAME} is running but database connection failed."


@kqk_router.post("/chat", tags=["Chat"], summary="Chat with Kumquat King")
async def chat(wx_msg: WXWorkIn, db: Session = Depends(get_db)):
    """
    处理企业微信消息的接口
    集成Langgraph工作流进行智能消息处理
    
    Args:
        wx_msg: 企业微信消息对象
        db: 数据库会话（通过依赖注入）
    """
    # 创建ChatHandler实例，传入数据库会话
    chat_handler = ChatHandler(wx_msg, db)
    chat_handler.init_requestor()
    try:
        logger.info(f"[聊天接口] 📨 收到企业微信消息: {wx_msg}")
        
        # 消息去重检查
        deduplicator = get_message_deduplicator()
        is_duplicate, cached_response = deduplicator.check_duplicate(wx_msg.msgid)
        
        if is_duplicate:
            logger.info(f"[聊天接口] 🔄 跳过重复消息: {wx_msg.msgid}")
            # 如果有缓存的回复内容，返回缓存内容；否则返回空内容
            return {"content": cached_response or ""}
        
        if wx_msg.msgtype == 'text' and wx_msg.text:
            content = wx_msg.text.content
            from_user = wx_msg.from_.userid
            
            logger.info(f"[聊天接口] 👤 {from_user}: {content}")
            
            # 集成Langgraph工作流处理消息
            try:                
                # 直接使用WXWorkIn格式（企业微信消息格式）
                workflow = get_kqk_workflow() 
                reply_content = workflow.process_message_sync_with_db(wx_msg, chat_handler, db)
                chat_handler.set_ai_answer(reply_content)
                
                # 存储回复内容到缓存
                deduplicator.store_response(wx_msg.msgid, reply_content)
                
            except Exception as workflow_error:
                logger.error(f"[聊天接口] ❌ Langgraph工作流处理失败: {workflow_error}")
                
                logger.error(f"[聊天接口] 📍 工作流异常详情: {traceback.format_exc()}")
                
                # 记录工作流处理失败
                chat_handler.add_action(ActionType.WORKFLOW_ERROR.value)
                chat_handler.set_note(f"工作流异常: {str(workflow_error)}")
                
                # 降级到简单回复
                reply_content = f"🤖 金桔王AI助手收到您的消息：{content}\n\n系统正在升级中，暂时使用简化回复模式。"
                chat_handler.set_answer(reply_content, f"ERROR: {traceback.format_exc()}")
                
                # 存储降级回复内容到缓存
                deduplicator.store_response(wx_msg.msgid, reply_content)
            
            logger.info(f"[聊天接口] ✅ 最终回复: {reply_content}")
            
            # 存储聊天记录到数据库
            try:
                await chat_handler.build_chat()
            except Exception as db_error:
                logger.error(f"[聊天接口] ❌ 保存聊天记录失败: {db_error}")
                import traceback
                logger.error(f"[聊天接口] 📍 数据库异常详情: {traceback.format_exc()}")
            
            # 返回简单的content格式，方便ECS转发处理
            return {"content": reply_content}
        else:
            logger.warning(f"[聊天接口] ❓ 不支持的消息类型: {wx_msg.msgtype}")
            fallback_response = "🤖 暂不支持此类型消息，请发送文字消息与我交流"
            
            # 记录不支持的消息类型
            chat_handler.add_action("UNSUPPORTED_MESSAGE_TYPE")
            chat_handler.set_answer(fallback_response)
            chat_handler.set_note(f"不支持的消息类型: {wx_msg.msgtype}")
            
            # 存储聊天记录到数据库
            try:
                await chat_handler.build_chat()
            except Exception as db_error:
                logger.error(f"[聊天接口] ❌ 保存聊天记录失败: {db_error}")
            
            # 存储降级回复内容到缓存
            deduplicator.store_response(wx_msg.msgid, fallback_response)
            return {"content": fallback_response}
            
    except Exception as e:
        logger.error(f"[聊天接口] ❌ 处理异常: {e}")
        import traceback
        logger.error(f"[聊天接口] 📍 异常详情: {traceback.format_exc()}")
        
        # 记录处理异常
        chat_handler.add_action("PROCESSING_ERROR")
        chat_handler.set_note(f"处理异常: {str(e)}")
        
        error_response = "🤖 处理消息时发生错误，请稍后重试"
        chat_handler.set_answer(error_response, f"ERROR: {traceback.format_exc()}")
        
        # 存储聊天记录到数据库
        try:
            await chat_handler.build_chat()
        except Exception as db_error:
            logger.error(f"[聊天接口] ❌ 保存聊天记录失败: {db_error}")
        
        # 尝试存储错误回复到缓存
        try:
            deduplicator = get_message_deduplicator()
            deduplicator.store_response(wx_msg.msgid, error_response)
        except:
            pass
        return {"content": error_response}

# wxcpt = WXBizJsonMsgCrypt(base_config.WX_TOKEN, base_config.WX_ENCODING_AES_KEY, base_config.WX_CORP_ID)
wxcpt = WXBizJsonMsgCrypt(base_config.WX_TOKEN, base_config.WX_ENCODING_AES_KEY, "") # 用于验证URL

@kqk_router.get("/callback")
def verify(
    msg_signature: str = Query(..., alias="msg_signature"),
    timestamp: str = Query(...),
    nonce: str = Query(...),
    echostr: str = Query(...)
):
    """
    企业微信回调URL验证
    """
    try:
        logger.info(f"[回调验证] 🔐 开始验证回调URL")
        logger.debug(f"[回调验证] 参数 - msg_signature: {msg_signature}, timestamp: {timestamp}, nonce: {nonce}")
        
        # 验证回调URL
        ret, sEchoStr = wxcpt.VerifyURL(msg_signature, timestamp, nonce, echostr)
        
        if ret == 0:
            logger.info(f"[回调验证] ✅ URL验证成功")
            return Response(content=sEchoStr, media_type="text/plain")
        else:
            logger.error(f"[回调验证] ❌ URL验证失败，错误码: {ret}")
            return Response(content="验证失败", status_code=400)
            
    except Exception as e:
        logger.error(f"[回调验证] ❌ 验证异常: {e}")
        import traceback
        logger.error(f"[回调验证] 📍 异常详情: {traceback.format_exc()}")
        return Response(content="验证异常", status_code=500)


@kqk_router.post("/callback")
async def callback(
    request: Request,
    msg_signature: str = Query(..., alias="msg_signature"),
    timestamp: str = Query(...),
    nonce: str = Query(...)
):
    """
    企业微信消息回调处理
    用于ECS中转站接收企业微信消息，解密后转发到本地处理
    """
    try:
        logger.info(f"[消息回调] 📨 收到企业微信回调消息")
        
        # 获取请求体
        body = await request.body()
        logger.debug(f"[消息回调] 原始消息体: {body.decode('utf-8')}")
        
        # 解密消息
        ret, sMsg = wxcpt.DecryptMsg(body.decode('utf-8'), msg_signature, timestamp, nonce)
        
        if ret != 0:
            logger.error(f"[消息回调] ❌ 消息解密失败，错误码: {ret}")
            return {"error": f"消息解密失败，错误码: {ret}"}
        
        logger.info(f"[消息回调] 🔓 消息解密成功")
        logger.debug(f"[消息回调] 解密后消息: {sMsg}")
        
        # 解析JSON消息
        try:
            msg_data = json.loads(sMsg)
            logger.debug(f"[消息回调] 解析后消息数据: {msg_data}")
            
            # 转换为WXWorkIn格式
            wx_msg = WXWorkIn(**msg_data)
            logger.info(f"[消息回调] 📋 消息转换成功: {wx_msg}")
            
        except Exception as parse_error:
            logger.error(f"[消息回调] ❌ 消息解析失败: {parse_error}")
            return {"error": f"消息解析失败: {str(parse_error)}"}
        
        # 转发到本地处理接口
        try:
            logger.info(f"[消息回调] 🔄 转发消息到本地处理: {base_config.LOCAL_CHAT_URL}")
            
            async with httpx.AsyncClient(timeout=30.0) as client:
                response = await client.post(
                    base_config.LOCAL_CHAT_URL,
                    json=wx_msg.model_dump(),
                    headers={"Content-Type": "application/json"}
                )
                
                if response.status_code == 200:
                    result = response.json()
                    logger.info(f"[消息回调] ✅ 本地处理成功，回复: {result.get('content', '')[:100]}...")
                    return result
                else:
                    logger.error(f"[消息回调] ❌ 本地处理失败，状态码: {response.status_code}")
                    return {"content": "🤖 系统暂时无法处理您的消息，请稍后重试"}
                    
        except httpx.TimeoutException:
            logger.error(f"[消息回调] ⏰ 转发超时")
            return {"content": "🤖 系统响应超时，请稍后重试"}
        except Exception as forward_error:
            logger.error(f"[消息回调] ❌ 转发异常: {forward_error}")
            import traceback
            logger.error(f"[消息回调] 📍 转发异常详情: {traceback.format_exc()}")
            return {"content": "🤖 系统处理异常，请稍后重试"}
            
    except Exception as e:
        logger.error(f"[消息回调] ❌ 回调处理异常: {e}")
        import traceback
        logger.error(f"[消息回调] 📍 异常详情: {traceback.format_exc()}")
        return {"content": "🤖 系统异常，请稍后重试"}